home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / tex / cut_past.zip / GETOPT.C < prev    next >
Text File  |  1987-03-04  |  4KB  |  166 lines

  1. /*
  2.  * getopt(), a verson of getopt for those who do not have it and do not
  3.  * want to steal the source from those that do.
  4.  *
  5.  * Same as getopt(3).
  6.  *    Returns the next option letter in argv that matches a letter in optstr.
  7.  *    Options are no longer parsed if the special option '--' is found
  8.  *    or an argument that does not start in '-'.
  9.  *    The global optind is set to the next index in argv to be processed.
  10.  *    The global optarg is set to the argument, if the option has one.
  11.  *    The global opterr can be set true if error messages are to be printed
  12.  *    on the standard error file, or false if no message to be printed.
  13.  *
  14.  * ARGUMENTS:
  15.  *    argc, argv - the argument count, and argument list
  16.  *    optstr     - the list of valid options. The character ":" following
  17.  *             an option letter indicates that this option must have an 
  18.  *             argument. For example "abc:". This implies that the -:
  19.  *             is not  a valid option.
  20.  *
  21.  * RETURNS:
  22.  *    Returns the next option letter, or EOF when all done. If an error
  23.  *    encountered then the character '?' is returned.
  24.  *
  25.  * John Weald
  26.  */
  27. #include <stdio.h>
  28.  
  29. /*
  30.  * Index into error array.
  31.  */
  32. #define BAD_OPT 0    /* option letter not in optstr            */
  33. #define MIS_ARG 1    /* option must have an argument            */
  34.  
  35. char *optarg;
  36. int optind = 1;        /* argv[0] is program name            */
  37. int opterr = 1;        /* If true print error message            */
  38.  
  39. /*
  40.  *
  41.  * The basic data structures are optind, and the pointer "p."
  42.  * optind keeps track of the next index into argv to parse arguments.
  43.  * p is used to walk along the argv items looking for option letters or
  44.  * arguments, when it is NULL the next  argv must be used . 
  45.  * p is always left pointing to the previous option or NULL.
  46.  * Consider the three equivalent valid argv's:
  47.  *        1        2         3
  48.  *        -a     -b       eric
  49.  *            -ab    eric
  50.  *        -aberic
  51.  * 
  52.  */
  53.  
  54. int
  55. getopt(argc, argv, optstr, progname)
  56. int argc;
  57. char *argv[];
  58. char *optstr;        /* The list of valid options            */
  59. char *progname;        /* Program name */
  60. {
  61.     extern err();    /* Forward reference            */
  62.  
  63.     static char *p = NULL;
  64.  
  65.     /*
  66.      * parsed all the options in this argv[]?
  67.      */
  68.     if (p == NULL || *++p == '\0' )
  69.     {
  70.         if (optind == argc)
  71.             return(EOF);
  72.         p = argv[optind];
  73.  
  74.         /*  a '-' by itself is not an option (e.g. see paste(1)) */
  75.         if (*p++ != '-' || *p == '\0') 
  76.             return(EOF);
  77.  
  78.         /* '--' marks the end of the option list.  */
  79.         if (*p == '-')
  80.         {
  81.             optind++;
  82.             return(EOF);
  83.         }
  84.     }
  85.  
  86.     optind++;
  87.     /*
  88.      * Look for a valid option 
  89.      */
  90.     while (*p != *optstr)
  91.     {    
  92.         if (*optstr == '\0')
  93.         {
  94.             /* Reached end of optstr, option not there */
  95.             err(progname, BAD_OPT, *p);
  96.             return((int)'?');
  97.         }
  98.         if (*++optstr == ':')
  99.             optstr++;
  100.     }
  101.  
  102.     /* If it does not need an argument then we are done.  */
  103.     if (*(optstr + 1) != ':')
  104.         return((int)*optstr);
  105.     
  106.     /*
  107.      * If there are more characters in this argv then it must
  108.      * be the argument.
  109.      */
  110.     if (*++p != '\0')
  111.     {
  112.         optarg = p;
  113.         p = (char *)NULL;
  114.         return((int)*optstr);
  115.     }
  116.  
  117.     /* 
  118.      * It needs an argument, but no more argv's left
  119.      */
  120.     if (optind == argc)
  121.     {
  122.         err(progname, MIS_ARG, *optstr);
  123.         p = (char *)NULL;
  124.         return((int)'?');
  125.     }
  126.  
  127.     /*
  128.      * Must be in next argv.
  129.      */
  130.     optarg = argv[optind++];
  131.     p = (char *)NULL;
  132.     return((int)*optstr);
  133. }
  134.  
  135. static 
  136. err(a0, e, c)
  137. char *a0;        /* argv[0]. i.e. the program name        */
  138. int e;
  139. char c;
  140. {
  141. #ifdef NO_STDIO
  142.     static char *errors[] = {
  143.         ": Illegal option -- ",
  144.         ": option requires an argument -- "
  145.     };
  146.     static char eend[] = "c\n";
  147.     
  148.  
  149.     if (opterr)
  150.     {
  151.         write(2, a0, strlen(a0));
  152.         write(2, errors[e], strlen(errors[e]));
  153.         eend[0] = c;
  154.         write(2, eend, strlen(eend));
  155.     }
  156. #else
  157.     static char *errors[] = {
  158.         "%s: Illegal option -- %c\n",
  159.         "%s: option requires an argument -- %c\n"
  160.     };
  161.  
  162.     if (opterr)
  163.         fprintf(stderr, errors[e], a0, c);
  164. #endif
  165. }
  166.